package bingosoft.metro.datasync.uuap.service;

import bingosoft.components.base.helper.ObjectHelper;
import bingosoft.components.base.service.Result;
import bingosoft.components.base.service.ResultEntity;
import bingosoft.metro.datasync.base.service.SyncService;
import bingosoft.metro.datasync.uuap.UuapClientFactory;
import bingosoft.metro.datasync.uuap.client.form.UserDataForm;
import bingosoft.metro.datasync.uuap.client.form.UserOrgDataForm;
import bingosoft.metro.datasync.uuap.client.param.RequestParam;
import bingosoft.metro.datasync.uuap.client.service.DataClientService;
import bingosoft.metro.datasync.uuap.model.SyncOrgUserRefModel;
import bingosoft.metro.datasync.uuap.model.SyncUserModel;
import leap.core.AppContext;
import leap.core.transaction.TransactionStatus;
import leap.lang.Strings;
import leap.orm.model.Model;
import org.dom4j.DocumentException;
import org.dom4j.Element;

import java.util.*;

/**
 * @author Feily
 * @功能描述 用户增量同步数据服务类
 * @创建时间 2017-12-13
 */
public class UserSyncService extends SyncService {
	
	/**
	 * 组织用户关系列表
	 */
	protected List<SyncOrgUserRefModel> userOrgRefs = new ArrayList<SyncOrgUserRefModel>();
	
	/**
	 * 用户角色关系列表
	 */
	//protected List<SyncUserRoleRefModel> userRoleRefs = new ArrayList<SyncUserRoleRefModel>();

	/**
	 * 用户组织角色关系列表
	 */
	//protected List<SyncUserOrgRoleRefModel> userOrgRoleRefs = new ArrayList<SyncUserOrgRoleRefModel>();
	
	/**
	 * 删除组织用户关系中间表SQL
	 */
	protected String deleteUserOrgSyncDataSql;
	/**
	 * 删除组织用户关系目标表SQL
	 */
	protected String deleteUserOrgTargetDataSql;
	/**
	 * 保存组织用户关系目标表SQL
	 */
	protected String saveUserOrgTargetDataSql;
	
	/**
	 * 删除用户角色关系中间表SQL
	 */
	//protected String deleteUserRoleSyncDataSql;
	/**
	 * 删除用户角色关系目标表SQL
	 */
	//protected String deleteUserRoleTargetDataSql;
	/**
	 * 保存用户角色关系目标表SQL
	 */
	//protected String saveUserRoleTargetDataSql;
	
	/**
	 * 删除用户组织角色关系中间表SQL
	 */
	//protected String deleteUserOrgRoleSyncDataSql;
	/**
	 * 删除用户组织角色关系目标表SQL
	 */
	//protected String deleteUserOrgRoleTargetDataSql;
	/**
	 * 保存组织角色关系目标表SQL
	 */
	//protected String saveOrgRoleTargetDataSql;
	/**
	 * 保存用户组织角色关系目标表SQL
	 */
	//protected String saveUserOrgRoleTargetDataSql;


	/**
	 * 构建函数
	 */
	public UserSyncService() throws DocumentException {
		this.setLogClass(this.getClass());
		
		this.tenantCode = AppContext.config().getProperty("uuap.tenantCode");
		this.syncType = "user";
		this.syncConfigDocPath = "/conf/config/sync-user-config.xml";

		if(useCustomSql){
			this.getLastSyncTimeSql = this.getSqlContent("uuap-user-getLastSyncTime");
			this.saveTargetDataSql = this.getSqlContent("uuap-user-saveTargetData");
			this.updateTargetDataSql = this.getSqlContent("uuap-user-updateTargetData");
			this.deleteTargetDataSql = this.getSqlContent("uuap-user-deleteTargetData");

			this.deleteUserOrgTargetDataSql = this.getSqlContent("uuap-userOrg-deleteTargetData");
			this.saveUserOrgTargetDataSql = this.getSqlContent("uuap-userOrg-saveTargetData");
		}else{
			this.getLastSyncTimeSql = this.buildGetLastUpdateTimeSql();
			this.saveTargetDataSql = this.buildSaveTargetDataSql();
			this.updateTargetDataSql = this.buildUpdateTargetDataSql();
			this.deleteTargetDataSql = this.buildDeleteTargetDataSql();

			this.deleteUserOrgTargetDataSql = this.buildDeleteUserOrgTargetDataSql();
			this.saveUserOrgTargetDataSql = this.buildSaveUserOrgTargetDataSql();
		}

		//删除用户同步中间表数据SQL
		this.deleteSyncDataSql = this.getSqlContent("uuap-user-deleteSyncData");

		//删除用户组织关系同步中间表数据SQL
		this.deleteUserOrgSyncDataSql = this.getSqlContent("uuap-userOrg-deleteSyncData");

		/*this.deleteUserRoleSyncDataSql = this.getSqlContent("uuap-userRole-deleteSyncData");
		this.deleteUserRoleTargetDataSql = this.getSqlContent("uuap-userRole-deleteTargetData");
		this.saveUserRoleTargetDataSql = this.getSqlContent("uuap-userRole-saveTargetData");
		
		this.deleteUserOrgRoleSyncDataSql = this.getSqlContent("uuap-userOrgRole-deleteSyncData");
		this.deleteUserOrgRoleTargetDataSql = this.getSqlContent("uuap-userOrgRole-deleteTargetData");
		this.saveOrgRoleTargetDataSql = this.getSqlContent("uuap-userOrgRole-saveOrgRoleTargetData");
		this.saveUserOrgRoleTargetDataSql = this.getSqlContent("uuap-userOrgRole-saveTargetData");*/
	}

	@Override
	public Result deleteSyncData() {
		this.logMethodCalled("deleteSyncData");
	
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("tenantCode", this.tenantCode);
		
		// 删除用户组织关系
		getDao().executeUpdate(this.deleteUserOrgSyncDataSql, params);	
		
		// 删除用户角色关系
		//getDao().executeUpdate(this.deleteUserRoleSyncDataSql, params);
		
		// 删除用户组织角色关系
		//getDao().executeUpdate(this.deleteUserOrgRoleSyncDataSql, params);
		
		// 删除用户
		getDao().executeUpdate(this.deleteSyncDataSql, params);	
		
		return new Result();
	}
	
	@Override
	public Result saveSyncData(List<Model> syncData){
		this.logMethodCalled("saveSyncData");
		
		// 保存用户
		getDao().batchInsert(syncData);
		
		// 保存用户组织关系
		getDao().batchInsert(this.userOrgRefs);
		
		// 保存用户角色关系
		//getDao().batchInsert(this.userRoleRefs);
		
		// 保存用户组织角色关系
		//getDao().batchInsert(this.userOrgRoleRefs);

		return new Result();
	}
	
	@Override
	public Result syncTargetData() {
		this.logMethodCalled("syncTargetData");

		Map<String, Object> params = new HashMap<String, Object>();
		params.put("tenantCode", this.tenantCode);

		getDao().doTransaction((TransactionStatus s)->{

			// 删除目标表中的已删除数据
			if(this.physicallyDelete){
				getDao().executeUpdate(this.deleteTargetDataSql, params);
			}

			// 修改目标用户数据
			getDao().executeUpdate(this.updateTargetDataSql, params);

			// 保存目标用户数据
			getDao().executeUpdate(this.saveTargetDataSql, params);

			// 删除目标用户组织关系数据
			getDao().executeUpdate(this.deleteUserOrgTargetDataSql, params);

			// 保存目标用户组织关系数据
			getDao().executeUpdate(this.saveUserOrgTargetDataSql, params);

		});

		// 删除目标用户角色关系数据
		//getDao().executeUpdate(this.deleteUserRoleTargetDataSql, params);
		
		// 删除目标用户组织角色关系数据
		//getDao().executeUpdate(this.deleteUserOrgRoleTargetDataSql, params);
				
		// 保存目标用户角色关系数据
		//getDao().executeUpdate(this.saveUserRoleTargetDataSql, params);
		
		// 保存目标组织角色数据
		//getDao().executeUpdate(this.saveOrgRoleTargetDataSql, params);
		
		// 保存目标用户组织角色关系数据
		//getDao().executeUpdate(this.saveUserOrgRoleTargetDataSql, params);
		
		return new Result();
	}
	
	@Override
	public List<Model> getSyncDataList(Date lastSyncTime) {
		this.logMethodCalled("getSyncDataList");
		this.logParamValue("lastSyncTime", lastSyncTime);
		
		List<Model> list = new ArrayList<Model>();
		
		DataClientService service  = UuapClientFactory.getDataClientService();
		
		RequestParam requestParam = new RequestParam();
		requestParam.setUpdateBeginDate(lastSyncTime);
		requestParam.setUpdateEndDate(new Date());
		
		ResultEntity<List<UserDataForm>> resultEntity = service.queryUsers(requestParam);
		if(!resultEntity.isSuccess()){
			throw new RuntimeException(resultEntity.getMessage());
		}
		
		// 构建数据
		List<UserDataForm> users = resultEntity.getBusinessObject();
		for (UserDataForm userDataForm : users) {
			
			// 构建用户
			SyncUserModel user = new SyncUserModel();
			userDataForm.copyTo(user);
			user.setTenantCode(this.tenantCode);
			
			user.setSyncId(ObjectHelper.getUUID());
			user.setSyncTime(new Date());
			user.setIsSync(true);
			list.add(user);
			
			// 构建用户组织关系列表
			for (UserOrgDataForm userOrgDataForm : userDataForm.getOrgs()) {
				SyncOrgUserRefModel ref = new SyncOrgUserRefModel();
				
				ref.setOrgUserId(userOrgDataForm.getOrgUserId());
				ref.setOrgId(userOrgDataForm.getOrgId());
				ref.setIsDefaultOrg(userOrgDataForm.isDefault());
				ref.setOrderNum(userOrgDataForm.getOrderNum());
				
				ref.setUserId(userDataForm.getUserId());
				ref.setCreateTime(userDataForm.getCreateTime());
				ref.setCreateUserId(userDataForm.getCreateUserId());
				ref.setUpdateTime(userDataForm.getUpdateTime());
				ref.setUpdateUserId(userDataForm.getUpdateUserId());
				ref.setTenantCode(this.tenantCode);
				
				ref.setColumn1(userOrgDataForm.getColumn1());
				ref.setColumn2(userOrgDataForm.getColumn2());
				ref.setColumn3(userOrgDataForm.getColumn3());
				ref.setColumn4(userOrgDataForm.getColumn4());
				ref.setColumn5(userOrgDataForm.getColumn5());
				
				ref.setSyncId(ObjectHelper.getUUID());
				ref.setSyncTime(new Date());
				ref.setIsSync(user.getIsSync());
				this.userOrgRefs.add(ref);
			}
			
			// 构建用户角色关系列表
			/*for (UserRoleDataForm userRoleDataForm : userDataForm.getRoles()) {
				SyncUserRoleRefModel ref = new SyncUserRoleRefModel();
				
				ref.setUserRoleId(userRoleDataForm.getUserRoleId());
				ref.setRoleId(userRoleDataForm.getRoleId());
				ref.setOrderNum(userRoleDataForm.getOrderNum());
				
				ref.setUserId(userDataForm.getUserId());
				ref.setCreateTime(userDataForm.getCreateTime());
				ref.setCreateUserId(userDataForm.getCreateUserId());
				ref.setUpdateTime(userDataForm.getUpdateTime());
				ref.setUpdateUserId(userDataForm.getUpdateUserId());
				ref.setTenantCode(this.tenantCode);
				
				ref.setSyncId(ObjectHelper.getUUID());
				ref.setSyncTime(new Date());
				ref.setIsSync(user.getIsSync());
				this.userRoleRefs.add(ref);
			}*/
			
			// 构建用户组织角色关系列表
			/*for (UserOrgRoleDataForm userOrgRoleDataForm : userDataForm.getOrgRoles()) {
				SyncUserOrgRoleRefModel ref = new SyncUserOrgRoleRefModel();
				
				ref.setUserOrgRoleId(userOrgRoleDataForm.getUserOrgRoleId());
				ref.setOrgRoleId(userOrgRoleDataForm.getOrgRoleId());
				ref.setOrgId(userOrgRoleDataForm.getOrgId());
				ref.setRoleId(userOrgRoleDataForm.getRoleId());
				ref.setOrderNum(userOrgRoleDataForm.getOrderNum());
				
				ref.setUserId(userDataForm.getUserId());
				ref.setCreateTime(userDataForm.getCreateTime());
				ref.setCreateUserId(userDataForm.getCreateUserId());
				ref.setUpdateTime(userDataForm.getUpdateTime());
				ref.setUpdateUserId(userDataForm.getUpdateUserId());
				ref.setTenantCode(this.tenantCode);
				
				ref.setSyncId(ObjectHelper.getUUID());
				ref.setSyncTime(new Date());
				ref.setIsSync(user.getIsSync());
				this.userOrgRoleRefs.add(ref);
			}*/
		}
		
		return list;
	}

	public List<SyncOrgUserRefModel> getUserOrgRefs() {
		return userOrgRefs;
	}

	public void setUserOrgRefs(List<SyncOrgUserRefModel> userOrgRefs) {
		this.userOrgRefs = userOrgRefs;
	}

	/*public List<SyncUserRoleRefModel> getUserRoleRefs() {
		return userRoleRefs;
	}

	public void setUserRoleRefs(List<SyncUserRoleRefModel> userRoleRefs) {
		this.userRoleRefs = userRoleRefs;
	}

	public List<SyncUserOrgRoleRefModel> getUserOrgRoleRefs() {
		return userOrgRoleRefs;
	}

	public void setUserOrgRoleRefs(List<SyncUserOrgRoleRefModel> userOrgRoleRefs) {
		this.userOrgRoleRefs = userOrgRoleRefs;
	}*/


	/**
	 * 删除目标用户组织关系数据SQL
	 * @return
	 * @throws DocumentException
	 */
	public String buildDeleteUserOrgTargetDataSql() throws DocumentException {

		//根元素
		Element rootElement = this.getSyncConfigDoc().getRootElement();
		//表配置元素
		Element config = rootElement.element("userOrg");
		//表配置元素
		Element table = config.element("table");
		//主键配置元素
		Element key = config.element("key");
		//目标表名
		String targetTable = table.getText();
		//源表名
		String sourceTable = table.attributeValue("sourceTable");
		//目标主键
		String targetKey = key.getText();
		//源主键
		String sourceKey = key.attributeValue("sourceColumn");
		//sql模板
		String sql = this.fullDeleteTargetDataSqlTmpl;

		//替换参数
		sql = sql.replaceAll("#targetTable#", targetTable)
				.replaceAll("#sourceTable#", sourceTable)
				.replaceAll("#targetKey#", targetKey)
				.replaceAll("#sourceKey#", sourceKey);

		return sql;
	}

	/**
	 * 保存用户组织关系目标数据
	 * @return
	 * @throws DocumentException
	 */
	public String buildSaveUserOrgTargetDataSql() throws DocumentException {

		//根元素
		Element rootElement = this.getSyncConfigDoc().getRootElement();
		//表配置元素
		Element config = rootElement.element("userOrg");
		//表配置元素
		Element table = config.element("table");
		//列配置元素
		Element columns = config.element("columns");
		//目标表名
		String targetTable = table.getText();
		//源表名
		String sourceTable = table.attributeValue("sourceTable");
		//sql模板
		String sql = this.fullSaveTargetDataqlTmpl;
		//目标列
		String targetColumns = "";
		//源列
		String sourceColumns = "";

		//循环读取配置
		for (Iterator iter = columns.elementIterator("column"); iter.hasNext();) {
			Element ele = (Element) iter.next();
			String sourceName = ele.attribute("sourceColumn").getText();
			String targetName = ele.getText();
			if(Strings.isEmpty(sourceName) || Strings.isEmpty(targetName)){
				continue;
			}

			targetColumns += Strings.format(", {0}", targetName);
			sourceColumns += Strings.format(", {0}", sourceName);

		}

		//替换参数
		sql = sql.replaceAll("#targetTable#", targetTable)
				.replaceAll("#sourceTable#", sourceTable)
				.replaceAll("#targetColumns#", targetColumns.substring(1))
				.replaceAll("#sourceColumns#", sourceColumns.substring(1));

		return sql;
	}

}
